package main

import (
	"encoding/json"
	"github.com/bitly/go-simplejson"
	"os"
	"parking/src/globalvars"
	"parking/src/structs"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

var loadConfigMu sync.Mutex

func init() {
	LoadConfigInit(configPath, configName)
}

// 配置文件写入
func LocalStorageConnConfig(data []byte, filePath string, fileName string) {
	fullPath := filepath.Join(filePath, fileName)
	// os.O_WRONLY 以只写模式打开 os.O_TRUNC 若文件已存在，立即清空文件内容（截断为0字节） os.O_CREATE 当文件不存在时自动创建新文件
	file, err := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		logger.Errorf("打开文件失败 [%s]: %v", fullPath, err)
		return
	}
	defer file.Close()

	// 写入数据
	n, err := file.Write(data)
	if err != nil {
		logger.Errorf("写入文件失败 [%s]: %v", fullPath, err)
		return
	}
	if n != len(data) {
		logger.Errorf("写入不完整 [%s]: 预期 %d 字节，实际写入 %d 字节", fullPath, len(data), n)
		return
	}
}

// 配置文件初次加载
func LoadConfigInit(filePath string, fileName string) {
	loadConfigMu.Lock()
	defer loadConfigMu.Unlock()
	loaded := globalvars.GetLoadConfigStatus()
	// 配置已经初始化过 不再加载直接退出
	if loaded {
		return
	}
	// 设置配置文件名
	file := filepath.Join(filePath, fileName)
	// 打开 JSON 配置文件
	jsonFile, err := os.Open(file)
	if err != nil {
		logger.Error("文件读取失败:", err)
		return
	}
	defer jsonFile.Close()
	// 解析 JSON 数据
	payloadJson, err := simplejson.NewFromReader(jsonFile)
	if err != nil {
		// todo 程序考量
		logger.Error("配置文件解析失败", err)
	}
	//保存相机序列号和离线配置信息的映射
	camerasJsonArr, err := payloadJson.Get("config").Get("cameras").Array()
	if err != nil || len(camerasJsonArr) == 0 {
		logger.Error("无相机配置or获取相机配置错误")
	}
	for _, cameraJson := range camerasJsonArr {
		camerasInfo := structs.NewCamerasInfoStruct()
		cameraInfo := Convert[map[string]interface{}](cameraJson)
		devId := Convert[string](cameraInfo["devId"])
		ip := Convert[string](cameraInfo["ip"])
		port := Convert[string](cameraInfo["port"])
		ledChannel := Convert[string](cameraInfo["ledChannel"])
		ledAddress := Convert[string](cameraInfo["ledAddress"])
		openChannel := Convert[string](cameraInfo["openChannel"])
		camerasInfo.SetDevId(devId)
		camerasInfo.SetIp(ip)
		camerasInfo.SetPort(port)
		camerasInfo.SetLedChannel(ledChannel)
		camerasInfo.SetLedAddress(ledAddress)
		camerasInfo.SetOpenChannel(openChannel)
		camerasInfoMap[devId] = camerasInfo
		camerasTimerMap[devId] = time.Now()
	}
	logger.Infof("加载相机相关配置: %v", camerasInfoMap)
	//保存led显示器485串口设置
	led485JsonArr, _ := payloadJson.Get("config").Get("led485").Array()
	for _, led485Json := range led485JsonArr {
		led485InfoStruct := structs.NewLed485ConfigStruct()
		led485Info := Convert[map[string]interface{}](led485Json)
		channel := Convert[string](led485Info["channel"])
		bitrate := Convert[string](led485Info["bitrate"])
		address := Convert[string](led485Info["address"])
		led485InfoStruct.SetName(channel)
		baud, _ := strconv.Atoi(bitrate)
		led485InfoStruct.SetBaud(baud)
		led485InfoStruct.SetReadTimeout(0)
		led485InfoStruct.SetAddress(address)
		led485InfoList = append(led485InfoList, led485InfoStruct)
	}
	logger.Infof("加载led485配置: %v", led485InfoList)
	// 保存离线配置
	// 离线显示屏显示内容
	var config structs.Config
	errorShowsNode := payloadJson.Get("config").Get("errorShows")
	errorShowsBytes, err := errorShowsNode.MarshalJSON()
	if err != nil {
		logger.Error("配置文件序列化失败")
	}
	if err = json.Unmarshal(errorShowsBytes, &config.ErrorShows); err != nil {
		logger.Error("配置文件反序列化失败")
	}
	errorShows = config.ErrorShows
	offlineOpen, _ = payloadJson.Get("config").Get("offlineOpen").Int()
	cameraHeartbeat, _ := payloadJson.Get("config").Get("cameraHeartbeat").Int()
	deviceHeartbeat, _ := payloadJson.Get("config").Get("deviceHeartbeat").Int()
	cameraHeartbeatInterval = time.Duration(cameraHeartbeat) * time.Second
	deviceHeartbeatInterval = time.Duration(deviceHeartbeat) * time.Second
	logger.Infof("加载离线模式配置,offlineOpen:%v errorShows:%v", offlineOpen, errorShows)
	logger.Info("配置加载完毕")
	globalvars.SetLoadConfigStatus(true)
}

func ReloadConfig(filePath string, fileName string) {
	loadConfigMu.Lock()
	defer loadConfigMu.Unlock()
	// 设置配置文件名
	file := filepath.Join(filePath, fileName)
	// 打开 JSON 配置文件
	jsonFile, err := os.Open(file)
	if err != nil {
		logger.Error("文件读取失败:", err)
		return
	}
	defer jsonFile.Close()
	// 解析 JSON 数据
	payloadJson, err := simplejson.NewFromReader(jsonFile)
	if err != nil {
		// todo 程序考量
		logger.Error("配置文件解析失败", err)
	}
	//保存相机序列号和离线配置信息的映射
	camerasJsonArr, _ := payloadJson.Get("config").Get("cameras").Array()
	for _, cameraJson := range camerasJsonArr {
		camerasInfo := structs.NewCamerasInfoStruct()
		cameraInfo := Convert[map[string]interface{}](cameraJson)
		devId := Convert[string](cameraInfo["devId"])
		ip := Convert[string](cameraInfo["ip"])
		port := Convert[string](cameraInfo["port"])
		ledChannel := Convert[string](cameraInfo["ledChannel"])
		ledAddress := Convert[string](cameraInfo["ledAddress"])
		openChannel := Convert[string](cameraInfo["openChannel"])
		camerasInfo.SetDevId(devId)
		camerasInfo.SetIp(ip)
		camerasInfo.SetPort(port)
		camerasInfo.SetLedChannel(ledChannel)
		camerasInfo.SetLedAddress(ledAddress)
		camerasInfo.SetOpenChannel(openChannel)
		camerasInfoMap[devId] = camerasInfo
		camerasTimerMap[devId] = time.Now()
	}
	// todo
	logger.Infof("重新加载相机相关配置: %v", camerasInfoMap)
	//保存led显示器485串口设置
	led485JsonArr, _ := payloadJson.Get("config").Get("led485").Array()
	for _, led485Json := range led485JsonArr {
		led485InfoStruct := structs.NewLed485ConfigStruct()
		led485Info := Convert[map[string]interface{}](led485Json)
		channel := Convert[string](led485Info["channel"])
		bitrate := Convert[string](led485Info["bitrate"])
		address := Convert[string](led485Info["address"])
		led485InfoStruct.SetName(channel)
		baud, _ := strconv.Atoi(bitrate)
		led485InfoStruct.SetBaud(baud)
		led485InfoStruct.SetReadTimeout(0)
		led485InfoStruct.SetAddress(address)
		led485InfoList = append(led485InfoList, led485InfoStruct)
	}
	logger.Infof("重新加载led485配置: %v", led485InfoList)
	// 保存离线配置
	// 离线显示屏显示内容
	var config structs.Config
	errorShowsNode := payloadJson.Get("config").Get("errorShows")
	errorShowsBytes, err := errorShowsNode.MarshalJSON()
	if err != nil {
		logger.Error("配置文件序列化失败")
	}
	if err = json.Unmarshal(errorShowsBytes, &config.ErrorShows); err != nil {
		logger.Error("配置文件反序列化失败")
	}
	errorShows = config.ErrorShows
	offlineOpen, _ = payloadJson.Get("config").Get("offlineOpen").Int()
	cameraHeartbeat, _ := payloadJson.Get("config").Get("cameraHeartbeat").Int()
	deviceHeartbeat, _ := payloadJson.Get("config").Get("deviceHeartbeat").Int()
	cameraHeartbeatInterval = time.Duration(cameraHeartbeat) * time.Second
	deviceHeartbeatInterval = time.Duration(deviceHeartbeat) * time.Second
	logger.Infof("重新加载离线模式配置,offlineOpen:%v errorShows:%v", offlineOpen, errorShows)
	logger.Info("配置重新加载完毕")
	globalvars.SetLoadConfigStatus(true)
	led485Init(led485InfoList)
}

func Convert[T any](S interface{}) T {
	val, ok := S.(T)
	if !ok {
		logger.Errorf("数据转化异常:%v", S)
	}
	return val
}

//var (
//	configs = make(map[string]interface{})
//	mu      sync.RWMutex
//)
//// 注册任意类型的配置
//func Register(name string, cfg interface{}) {
//	mu.Lock()
//	defer mu.Unlock()
//	configs[name] = cfg
//}
//// 返回配置
//func Get(name string) interface{} {
//	mu.RLock()
//	defer mu.RUnlock()
//	return configs[name]
//}
